package com.example.demo.generator.scaffold.registry;

import com.example.demo.generator.scaffold.model.TemplateContext;
import com.example.demo.generator.scaffold.model.TemplateDescriptor;
import com.example.demo.generator.scaffold.util.ScaffoldNameUtils;

import java.util.List;

/**
 * Vue 前端模板集合。
 */
public final class FrontendVueTemplates {

    private FrontendVueTemplates() {
    }

    public static List<TemplateDescriptor> all() {
        return List.of(
                gitignore(),
                packageJson(),
                tsconfigJson(),
                tsconfigNodeJson(),
                viteConfig(),
                indexHtml(),
                mainTs(),
                appVue(),
                styleCss(),
                layoutComponent(),
                routerIndex(),
                homeView(),
                loginView(),
                registerView(),
                crudView(),
                apiModule(),
                typesModule(),
                authTypesModule(),
                envDts()
        );
    }

    private static TemplateDescriptor gitignore() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-gitignore")
                .templatePath("scaffold/templates/frontend/vue/gitignore.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/.gitignore")
                .build();
    }

    private static TemplateDescriptor packageJson() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-package-json")
                .templatePath("scaffold/templates/frontend/vue/package.json.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/package.json")
                .build();
    }

    private static TemplateDescriptor tsconfigJson() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-tsconfig-json")
                .templatePath("scaffold/templates/frontend/vue/tsconfig.json.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/tsconfig.json")
                .build();
    }

    private static TemplateDescriptor tsconfigNodeJson() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-tsconfig-node-json")
                .templatePath("scaffold/templates/frontend/vue/tsconfig.node.json.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/tsconfig.node.json")
                .build();
    }

    private static TemplateDescriptor viteConfig() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-vite-config")
                .templatePath("scaffold/templates/frontend/vue/vite.config.ts.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/vite.config.ts")
                .build();
    }

    private static TemplateDescriptor indexHtml() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-index-html")
                .templatePath("scaffold/templates/frontend/vue/index.html.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/index.html")
                .build();
    }

    private static TemplateDescriptor mainTs() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-main-ts")
                .templatePath("scaffold/templates/frontend/vue/src/main.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "main.ts"))
                .build();
    }

    private static TemplateDescriptor appVue() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-app-vue")
                .templatePath("scaffold/templates/frontend/vue/src/App.vue.ftl")
                .outputPathResolver(context -> srcPath(context, "App.vue"))
                .build();
    }

    private static TemplateDescriptor styleCss() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-style-css")
                .templatePath("scaffold/templates/frontend/vue/src/style.css.ftl")
                .outputPathResolver(context -> srcPath(context, "style.css"))
                .build();
    }

    private static TemplateDescriptor layoutComponent() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-layout")
                .templatePath("scaffold/templates/frontend/vue/src/components/BaseLayout.vue.ftl")
                .outputPathResolver(context -> srcPath(context, "components/BaseLayout.vue"))
                .build();
    }

    private static TemplateDescriptor routerIndex() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-router-index")
                .templatePath("scaffold/templates/frontend/vue/src/router/index.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "router/index.ts"))
                .build();
    }

    private static TemplateDescriptor homeView() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-home-view")
                .templatePath("scaffold/templates/frontend/vue/src/views/HomeView.vue.ftl")
                .outputPathResolver(context -> srcPath(context, "views/HomeView.vue"))
                .build();
    }

    private static TemplateDescriptor loginView() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-login-view")
                .templatePath("scaffold/templates/frontend/vue/src/views/LoginView.vue.ftl")
                .outputPathResolver(context -> srcPath(context, "views/LoginView.vue"))
                .build();
    }

    private static TemplateDescriptor registerView() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-register-view")
                .templatePath("scaffold/templates/frontend/vue/src/views/RegisterView.vue.ftl")
                .outputPathResolver(context -> srcPath(context, "views/RegisterView.vue"))
                .build();
    }

    private static TemplateDescriptor crudView() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-crud-view")
                .templatePath("scaffold/templates/frontend/vue/src/views/CrudView.vue.ftl")
                .outputPathResolver(context -> srcPath(context, "views/" + ScaffoldNameUtils.deriveFrontendVueViewComponentName(context) + ".vue"))
                .build();
    }

    private static TemplateDescriptor apiModule() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-api-module")
                .templatePath("scaffold/templates/frontend/vue/src/lib/api.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "lib/api.ts"))
                .build();
    }

    private static TemplateDescriptor typesModule() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-entity-types")
                .templatePath("scaffold/templates/frontend/vue/src/types/Entity.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "types/" + context.getClassInfo().getClassName() + ".ts"))
                .build();
    }

    private static TemplateDescriptor authTypesModule() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-auth-types")
                .templatePath("scaffold/templates/frontend/vue/src/types/Auth.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "types/auth.ts"))
                .build();
    }

    private static TemplateDescriptor envDts() {
        return TemplateDescriptor.builder()
                .id("frontend-vue-env-dts")
                .templatePath("scaffold/templates/frontend/vue/src/env.d.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "env.d.ts"))
                .build();
    }

    private static String resolveRoot(TemplateContext context) {
        return ScaffoldNameUtils.deriveFrontendProjectName(context);
    }

    private static String srcPath(TemplateContext context, String relative) {
        return resolveRoot(context) + "/src/" + relative;
    }
}

